fix(spec): register sys_package_version in CLOUD_PROVIDED_OBJECT_NAMES - #17214
Conversation
The curated cloud list carried sys_package and sys_package_installation but not the release-snapshot table between them, so the shipped sys_metadata.package_version_id lookup target was classed as a platform-prefixed name nothing registers. Add the one entry, pin it by name beside sys_license, and add the patch changeset. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH
📓 Docs Drift CheckThis PR changes 1 package(s): 2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 134 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 27b16955a2361c440efae489eac4948cecf7b2c1 && git checkout 27b16955a2361c440efae489eac4948cecf7b2c1
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin bccf311100cad7affccd6cbfcddbd81fe734d97d df37e65647f1100a615485a8850a6db549cc7afb && git checkout -B drift-repro bccf311100cad7affccd6cbfcddbd81fe734d97d && git merge --no-ff df37e65647f1100a615485a8850a6db549cc7afb
node scripts/docs-audit/affected-docs.mjs --json bccf311100cad7affccd6cbfcddbd81fe734d97d
|
…oud-provided-package-version
The clause-② declaration for this PR is `yes`: `CLOUD_PROVIDED_OBJECT_NAMES` is a closed accept set and this diff adds a member to it. A PR that declares clause ② must grade at least one package whose published source it moves at `minor` or above (`check-changeset-no-major.mjs`, level axis), and a purely additive widening of a published public surface takes at least `minor` by the `Check Changeset` "WHICH LEVEL" rule. `major` is refused by the same script's launch-window guard, so `minor` is the only legal grade. The changeset prose no longer frames the addition as restoring something the published header already promised — that reading was withdrawn: the header states why the list exists, not that this name is a member of it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH
…oud-provided-package-version
Fixes #16745
CLOUD_PROVIDED_OBJECT_NAMEScarriedsys_packageandsys_package_installation— the head and tail of the three-table package familypackages/spec/src/cloud/package.zod.tsdeclares — but notsys_package_version, the release-snapshot table between them, whose row schema this repository ships ascloud/package-version.zod.ts. Platform metadata that ships with the product references the name (sys_metadata.package_version_idis aField.lookup('sys_package_version', …)in@objectstack/metadata-core), so against the list's own stated purpose that shipped lookup target was being judged a platform-prefixed name nothing registers.This PR adds the one entry and pins it by name in the constant's test, beside the
sys_licensepin that landed for the same class of drift (#13842). Nothing underpackages/lintmoves: the reference ladder is correct, the list was short.Clause-②: yes
CLOUD_PROVIDED_OBJECT_NAMESis a closed accept set and this diff adds a member to it, so the lint ladder now accepts a name it previously warned on. That is a widening, and it takesyes.node scripts/pm/check-clause2-carriers.mjs --pair 17214fires C5/T2 atplatform-object-names.ts:156— "a new member of a closed set" — and the declaration now agrees with it.An earlier revision of this body declared
no, citing the list's header as contract text that already promised the name. Thedomain:specseat withdrew that reading: the header states why the list exists, not thatsys_package_versionis a member of it, and a purpose is not an enumeration. The carve-out it invoked — deleting a refusal the published text itself denies — therefore does not apply, and no machine-readable waiver exists for a prose argument in its place.needs:contract-reviewis hung on both carriers and is the review seat's to clear; this PR waits outside the queue until it is.--pairstill exits 4 on this head, and the reason is a carrier this PR cannot reach. C5 reads the declaration limb from the card's governing claim comment (cardDeclaration()over the card's comment thread), never from a PR body — the level axis incheck-changeset-no-major.mjsis the reader that takes the PR body, and that is the one this edit serves. Card #16745's claim comment still carries a line-startClause-②: no, so C5 reports the pair as illegible until the claiming seat re-declares it there. The checker's own header forbids anyone else from doing that on the seat's behalf — "the declaration IS the judgement" — so it is left, reported, and not written around.Premise re-derived on
origin/main, then re-derived again after the mergeorigin/main:git show origin/main:…/platform-object-names.tslistedsys_app,sys_environment,sys_environment_member,sys_license,sys_package,sys_package_installation— six members,sys_package_versionabsent, head and tail of the family present.git grep sys_package_version origin/main -- packages/metadata-core/src/objects/sys-metadata.object.ts→ line 76package_version_id: Field.lookup('sys_package_version', {still present.Both halves held; nothing had been landed since triage.
origin/mainwas merged in twice throughscripts/pm/os-regen-merge.sh— merge commits87751f84eand, this round,df37e6564— with no os-regen path needing a side taken and no generated artifact moving either time.Changeset —
@objectstack/specatminor, derived between a floor and a ceilingplatform-object-names.tsis not a.zod.ts, so it does not ship as source underfiles[]— butsrc/system/constants/index.tsre-exports it (export * from './platform-object-names'), so the constant ships compiled insidedist, which is infiles[]. Measured after the rebuild, with controls:sys_package_versionsys_licensedist/system/index.mjsdist/system/index.jsdist/index.mjsdist/browser/system/index.mjsapi-surface/system.jsonandexport-origins/system.jsonboth listCLOUD_PROVIDED_OBJECT_NAMES. So published behaviour moves ⇒ a changeset is owed andskip-changesetdoes not apply. The level was derived, not taken on anyone's word, and the floor and the ceiling meet at one value:pr-automation.yml'sCheck Changesetprose ("WHICH LEVEL", maintainer ruling 2026-09-04, batch [WIP] Add query enhancements and advanced validation features #35 on finding(changeset): two independent contract reviews read the repo's own history to opposite bumps for "add an exported symbol to a published index" #15294): "a purely additive widening of a published package's public surface (a new exported symbol on anindex, a new accepted key or value) takes at leastminor". A new accepted value is exactly what this is.check-changeset-no-major.mjs: a PR declaring clause ② "must grade AT LEAST ONE package whose published source it movesminoror above".@objectstack/specis the only package this diff moves, so it is that package.patchacross the board is verdictenforce, exit 1 — the red this grade change exists to prevent.majoris refused outright by the same script's launch-window guard, and noallow-majorlabel is on this PR..changeset/pre.jsonis absent, so the RC exemption that would stand the guard down is not in effect either.minoris therefore the only legal grade, and it is also the semantically right one: nothing is removed or narrowed, so no member's meaning changes for an existing consumer. No ADR-0087 disposition is owed — that gate reads breaking signals, which are amajorbump or a**BREAKING/BREAKING CHANGEmarker in the body, and this changeset carries neither.Locally the level axis reports
NOT APPLICABLE("nopull_requestpayload to read a declaration from") because the declaration it reads is PR-scoped; its real reading is CI'sCheck Changeseton this PR. The three changeset gates that DO have a local reading ondf37e6564all pass and print their own verdicts:Verification — final head
df37e6564Heavy runs went through
bash scripts/pm/os-verify-lock.shon slotissue-16745-resume.The full package suite, in one run, no
--projectfilter and no file list — so both vitest projects (localandrepo) are selected by the config, not by me:Re-taken on
df37e6564after this round's merge, ⛔ not carried over from the previous head.Proof the pin file was actually in that run — the reason this matters is that
platform-object-names.test.tsis one of the 28 entries invitest.repo-tests.json, so thelocalproject excludes it andpnpm testalone would never have run it. From the verbose reporter's own output, all nine cases of the file, tagged with the project that ran them:The last line is this PR's new case. The line above it is the pre-existing
sys_licensesibling, lit in the same run as the control.Ablation — the pin can fail, and fails for the right reason. Direction predicted before running: turns red. It was run on head
87751f84eand is ⛔ not re-run here, because the two files it exercises are byte-identical at the final head —platform-object-names.tshashesf691ad7939dac77330995e3d9db49e95182ad5dband its testb2a4cde719761206871181f1ff358753b2371ab9at BOTH87751f84eanddf37e6564, and this round's diff is one.changeset/*.md. Both legs ran under the lock, each proving its edit reached disk before the run was read:Exactly one of the nine cases moved, and it is the new one — the pin is load-bearing and precisely scoped. The restore is anchored at
HEAD, not a bare checkout, and is proven by hash equality plus an emptygit diff HEAD, not by an exit code.Other package-level runs, same lock acquisition, exit codes landed to disk before being read:
pnpm --filter @objectstack/spec build→BUILD_EXIT=0pnpm --filter @objectstack/spec typecheck(tsc + scripts tsconfig +check:test-typecheck) →TYPECHECK_EXIT=0. Both exit codes were echoed individually rather than read from the lock wrapper's batch verdict, which covers only the last part of a;-sequenced command and says so.pnpm --filter @objectstack/spec check:generated→ exit 0, andgit statusclean — no generated artifact moved. Consistent with the mechanism: nothing outsidepackages/specreadsCLOUD_PROVIDED_OBJECT_NAMES, andscripts/platform-object-tenancy-census.jsoncontains nosys_packagerow at all.@objectstack/specdeclares no@objectstack/*workspace dependency, sopnpm --filter '@objectstack/spec^...' buildis empty by construction; the package itself was built.Gate families ③/④ — derived mechanically, never from a hand-fed path list:
73 exited 0. Four exited 3 =
PREREQUISITE NOT MET, recorded as NOT MEASURED — neither green nor red — all four because they read built output for packages this worktree has not built, which CI builds fresh:@objectstack/lint check:doc-formula-expressions@objectstack/formulais not built"check:dual-build-cjs-loadscheck:lean-entry-closurepackages/objectql/dist/core.mjsabsentcheck:type-check-debtcheck:nul-bytesexited 0, and a separategrep -naPsweep for control characters over the three changed files found none. Repo-widepnpm lintis CI's run and was not attempted here.Not measured, by design of the contract
That
@objectstack/service-tenantactually registerssys_package_versionlives in thecloudrepository, which is not reachable from this session. The list's header says that half is owned there and cannot be conformance-tested from this repo. It is NOT MEASURED here — not verified, and not substituted with anything this repository can prove instead. Reported on the card as an out-of-scope finding for the seat to file cross-repo.验收备注
PLATFORM_PROVIDED_OBJECT_NAMES: 112 shipped*.object.tsfiles underpackages/+examples/, 135 reference targets, 109 of them platform-prefixed ⇒ 0 unregistered. Controls:sys_userappears as a target 61 times (lit),registry.has('sys_definitely_not_real')isfalse,registry.has('sys_package_version')istrue— the last also proving the dist read was the rebuilt one. This reproduces the card's measurement, which found exactly one finding in the whole universe, and brings it to zero.packages/spec/src/cloud/environment.zod.tsnamessys_environment_credentialas a control-plane table andtenant.zod.tsnames the deprecatedsys_tenant_database. Neither is declared here nor listed inCLOUD_PROVIDED_OBJECT_NAMES, and both are referenced by zero shipped*.object.tsfiles, so no false refusal reproduces today — which is what separates them from this card. Whether the cloud runtime registers them is the same unmeasurable half as above. 承接者: the seat filing the cross-repo card carries the question alongside.Generated by Claude Code
Generated by Claude Code